/*************************************************
main.cpp
Author:Mitom
Date:2019-05-30
Description:矩阵类
**************************************************/

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <regex>
#include <random>
#include <time.h>
#include <ctime>
#include "Matrix.hpp"
#include "Tensor.hpp"
#include "Filter.hpp"
#include "utils.hpp"
#include "tinyxml.h"
#include "stm32f10x_usart.h"

#define TIXML_USE_STL

using namespace std;

double strToDouble(string str)
{
	double result=atof(str.c_str());
	return result;
}

void run()
{
	Tensor tensor = Tensor(2,4,4);
	for(int i=0; i<2; i++){
		Matrix mat = Matrix(4,4,(i+1));
		tensor.addLayer(mat);
	}

	Filter filter = Filter(3, 2, 3, 3);

	Tensor tensor1 = tensor.forwardConv(filter, 1,1,1,1);
	tensor1.getLayer(0).setValue(0,0,-22.0);

	cout << "----------------------" << endl;
	tensor1.showTensor();
//	Tensor maxTensor = tensor1.forwardMaxpool(2,2);
//	maxTensor.getLayer(0).showMatrix();
//	maxTensor.getLayer(1).showMatrix();
//	maxTensor.getLayer(2).showMatrix();
	cout << "----------------------" << endl;
	tensor1.forwardReLu();
	tensor1.showTensor();
	tensor1.forwardFlat().showMatrix();

	Matrix weight = Matrix(48,10,1);
	weight.setValue(1,1,0.2);
	weight.setValue(5,5,33);
	Matrix out = Matrix::multiply(tensor1.forwardFlat(), weight);
	cout << "=====================" << endl;
	out.dotMatCoefficient(0.001);
	out.showMatrix();
	vector<int> outClass = out.softmax();
	out.showMatrix();

	for(size_t i=0; i<outClass.size(); i++){
		cout <<"sample " << i << " pred:" << outClass[i] << endl;
	}
}


void readParams()
{
	TiXmlDocument mydoc("conv1_0_weight_1.xml");//xml文档对象
	bool loadOk=mydoc.LoadFile();//加载文档
	if(!loadOk)
	{
		cout<<"could not load the test file.Error:"<<mydoc.ErrorDesc()<<endl;
		exit(1);
	}

	int fsize = 128;
	int depth = 64;
	int row = 3;
	int col = 1;

	Filter filter = Filter(fsize,depth,row,col);
	TiXmlElement *rootElem = mydoc.RootElement();	// filter
	TiXmlElement *fElem = rootElem;
	int fcount = 0;
	for(TiXmlElement *tensonElem = fElem->FirstChildElement();tensonElem != NULL;tensonElem = tensonElem->NextSiblingElement()){// tensor

		Tensor tensor = Tensor(row,col);
		for(TiXmlElement *matElem = tensonElem->FirstChildElement();matElem != NULL;matElem=matElem->NextSiblingElement()){ // matrix
			Matrix mat = Matrix(row,col);
			int row = 0;
			for(TiXmlElement *rowElem = matElem->FirstChildElement();rowElem != NULL;rowElem=rowElem->NextSiblingElement()){ // row
				mat.getPtr()[row][0] = strToDouble(rowElem->FirstChild()->Value());
				row++;
			}
			tensor.addLayer(mat);
		}
		filter.setFilter(fcount, tensor);
		fcount ++;
	}
}
//code above is for testing in PC
//code below is for running in STM32
void TIM4_Init(u16 arr,u16 psc)
{	
	NVIC_InitTypeDef NVIC_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //Ê±ÖÓÊ¹ÄÜ//TIM4Ê±ÖÓÊ¹ÄÜ    
	//¶¨Ê±Æ÷TIM3³õÊ¼»¯
	TIM_TimeBaseStructure.TIM_Period = arr; //ÉèÖÃÔÚÏÂÒ»¸ö¸üÐÂÊÂ¼þ×°Èë»î¶¯µÄ×Ô¶¯ÖØ×°ÔØ¼Ä´æÆ÷ÖÜÆÚµÄÖµ	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //ÉèÖÃÓÃÀ´×÷ÎªTIMxÊ±ÖÓÆµÂÊ³ýÊýµÄÔ¤·ÖÆµÖµ
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //ÉèÖÃÊ±ÖÓ·Ö¸î:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIMÏòÉÏ¼ÆÊýÄ£Ê½
	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õÊ¼»¯TIMxµÄÊ±¼ä»ùÊýµ¥Î»
	TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //Ê¹ÄÜÖ¸¶¨µÄTIM4ÖÐ¶Ï,ÔÊÐí¸üÐÂÖÐ¶Ï
	NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//ÇÀÕ¼ÓÅÏÈ¼¶3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;		//×ÓÓÅÏÈ¼¶3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQÍ¨µÀÊ¹ÄÜ
	NVIC_Init(&NVIC_InitStructure);	//¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õÊ¼»¯VIC¼Ä´æÆ÷
}
void TIM4_Set(u8 sta)
{
	if(sta)
	{      
		TIM_SetCounter(TIM4,0);//¼ÆÊýÆ÷Çå¿Õ
		TIM_Cmd(TIM4, ENABLE);  //Ê¹ÄÜTIMx	
	}
	else TIM_Cmd(TIM4, DISABLE);//¹Ø±Õ¶¨Ê±Æ÷4	   
}
void usart1_Init(int baudRate)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //´ò¿ª¸´ÓÃÊ±ÖÓ
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //´ò¿ª´®¿ÚÊ±ÖÓ

	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  //tx
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA,&GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //rx
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA,&GPIO_InitStructure);

	//ÅäÖÃ´®¿Ú 
	USART_InitStructure.USART_BaudRate = baudRate;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	USART_Init(USART1, &USART_InitStructure);
	
	//--- ÉèÖÃNVIC²ÎÊý ---
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);    
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; 	   				//´ò¿ªUSART1µÄÈ«¾ÖÖÐ¶Ï
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4; 	 //ÇÀÕ¼ÓÅÏÈ¼¶Îª0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 						//ÏìÓ¦ÓÅÏÈ¼¶Îª0
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 						 //Ê¹ÄÜ
	NVIC_Init(&NVIC_InitStructure);

	//--- ÉèÖÃÖÐ¶Ï ---
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //Ê¹ÄÜ´®¿Ú½ÓÊÕÖÐ¶Ï
	
	USART_ClearFlag(USART1,USART_FLAG_TC);	//Çå¿Õ·¢ËÍÍê³É±êÖ¾Î»
	USART_ClearFlag(USART1,USART_FLAG_RXNE);	//Çå¿Õ·¢ËÍÍê³É±êÎ»
	USART_Cmd(USART1, ENABLE); //´®¿ÚÊ¹ÄÜ
	
//	TIM4_Init(999,7199);		//10msÖÐ¶Ï
//	TIM4_Set(0);
}
void usart1_sendByte(u8 dat)
{
	USART_SendData(USART1, dat);
	while (USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET); // µÈ´ý·¢ËÍÍê³É
}
void usart1_sendString(char* str)
{
	u16 i=0;
	while(str[i])
	{
		usart1_sendByte(str[i++]);
	}
}
void Delayms(u16 ms)
{
	u32 temp;
	SysTick->LOAD=9000*ms;	  //??????, 72MHZ?
	SysTick->CTRL=0X01;		//??,???????,???????
	SysTick->VAL=0;			//?????
	do
	{
		temp=SysTick->CTRL;	   //????????
	}
	while((temp&0x01)&&(!(temp&(1<<16))));	//??????
	SysTick->CTRL=0;	//?????
	SysTick->VAL=0;		//?????
}
//main function
int main() {
//	clock_t startTime,endTime;
//	//run();
//	startTime = clock();
//	readParams();
//	endTime = clock();
//	cout << (endTime-startTime) /  (double)CLOCKS_PER_SEC << endl;
	usart1_Init(115200);
	string fuck="FUCK YOU!\r\n";
	int len=fuck.size();
	char p[50];
	fuck.copy(p,len,0);
	*(p+len)='\0';
	while(1){
		Delayms(1000);
		usart1_sendString(p);
	}
	return 0;
}















